package b.sync.sample

import zio._
import b.sync.domain._
import b.sync.domain.ZioExtractor._
import b.sync.domain.ZioReplicator._
import io.getquill.{EntityQuery, Literal, MySQLDialect, MysqlZioJdbcContext, Query, Quoted, SnakeCase, SqlMirrorContext}
import zio.console._
import io.getquill.context.ZioJdbc._

import java.sql.SQLException
import javax.sql

object ZioPckSync extends App {

  type SyncEnv = Console with ZioExtractor with ZioReplicator

//  val logic: RIO[SyncEnv, Unit] =
//    for {
//      rows  <- ZioExtractor.extract[TPckRow](0L)
//      _     <- putStrLn(s"extracted ${rows.length} rows:")
//      _     <- ZIO.foreach_(rows)(r => putStrLn(r.toString))
//      count <- ZioReplicator.replicate[TPckRow, TPckRow](rows)
//      _     <- putStrLn(s"replicated: $count")
//    } yield ()
//
//  val ext: ULayer[ZioExtractor] = ZLayer.succeed(new QuillSQLs)
//  val rep: ULayer[ZioReplicator] = ZLayer.succeed(new QuillReplicator)
//  val env = Console.live ++ ext ++ rep
  val ctx = new MysqlZioJdbcContext(SnakeCase)
  import ctx._

//  implicit val pckDecoder: Decoder[TPckRow] =
//    decoder((index, row, session) =>
//      TPckRow(row.getLong(index), t = new java.util.Date())) // database-specific implementation
//
//  implicit val pckEncoder: Encoder[TPckRow] =
//    encoder(java.sql.Types.OTHER, (index, value, row) =>
//      row.setObject(index, value, java.sql.Types.OTHER)) // database-specific implementation

  def extractSync(from: Long): Quoted[EntityQuery[TSyncX]] =
    quote(querySchema[TSyncX]("xp_t_pck").filter(r => r.syncRowNo > lift(from)))

  def extractRow(no: Long): Quoted[Query[TPckRow]] =
    quote(querySchema[TPckRow]("xp_t_pck").filter(_ => infix"sync_row_no = #$no".asCondition))

  val ds = DataSourceLayer.fromPrefix("jdbc")

  val logic: ZIO[Has[sql.DataSource] with Console, Exception, List[TSyncX]] =
    for {
      rows <- ctx.run(extractSync(2L))
      _    <- putStrLn(s"extracted ${rows.length} rows:")
      _    <- ZIO.foreach_(rows)(r => putStrLn(r.toString))
      pcks <- ZIO.foreach(rows) { r =>
        ctx.run(extractRow(r.syncRowNo)).map(p => XpPckRow(p.head, r.syncRowNo, r.syncOpType))
      }
      _    <- putStrLn(s"extracted ${pcks.length} pcks:")
      _    <- ZIO.foreach_(pcks)(r => putStrLn(r.toString))
    } yield rows

  override def run(args: List[String]): URIO[ZEnv, ExitCode] =
    logic.provideLayer(ds ++ Console.live).exitCode
}
